use futures::{future::BoxFuture, FutureExt};
use ulid::Ulid;

pub fn gen_ulid() -> String {
    let ulid = Ulid::new();
    ulid.to_string()
}

pub fn compose_async<F, G, T>(f: F, g: G) -> impl Fn(T) -> BoxFuture<'static, T>
where
    F: Fn(T) -> BoxFuture<'static, T> + Clone + Send + 'static,
    G: Fn(T) -> BoxFuture<'static, T> + Clone + Send + 'static,
    T: Clone + Send + 'static,
{
    move |arg: T| {
        let f = f.clone();
        let g = g.clone();
        async move {
            let res1 = f(arg).await;
            let res2 = g(res1.clone()).await;
            res2
        }
        .boxed()
    }
}

#[cfg(test)]
mod tests {
    use std::{any::{Any, TypeId}, collections::HashMap};

    use super::*;

    #[test]
    fn test_gen_ulid() {
        let ulid = gen_ulid();
        assert_eq!(ulid.len(), 26);
    }

    #[tokio::test]
    async fn test() {
        async fn fn_a(arg: String) -> String {
            format!("{}: A", arg)
        }

        async fn fn_b(arg: String) -> String {
            format!("{}: B", arg)
        }
        let async_a = |s: String| fn_a(s).boxed();
        let async_b = |s: String| fn_b(s).boxed();
        let composed = compose_async(async_a, async_b);
        let result = composed("test".to_string()).await;
        println!("{}", result);
    }

    #[test]
    fn test2() {
        use std::{slice::from_raw_parts, str::from_utf8_unchecked};

        // 获取字符串的内存地址和长度
        fn get_memory_location() -> (usize, usize) {
            let string = "Hello World!";
            let pointer = string.as_ptr() as usize;
            let length = string.len();
            (pointer, length)
        }

        // 在指定的内存地址读取字符串
        fn get_str_at_location(pointer: usize, length: usize) -> &'static str {
            unsafe { from_utf8_unchecked(from_raw_parts(pointer as *const u8, length)) }
        }

        let (pointer, length) = get_memory_location();
        let message = get_str_at_location(pointer, length);
        println!(
            "The {} bytes at 0x{:X} stored: {}",
            length, pointer, message
        );
        // 如果大家想知道为何处理裸指针需要 `unsafe`，可以试着反注释以下代码
        let message = get_str_at_location(1000, 10);
        println!("The {} bytes at 0x{:X} stored: {}", 10, 1000, message);
    }

    #[test]
    fn test3() {
        let mut num = 5;

        let r1 = &num as *const i32;

        unsafe {
            println!("r1 is: {}", *r1);
        }
    }

    #[tokio::test]
    async fn test4() {
        trait CallCore11<T: Send, R: Send> : Send + Sync {
            async fn run(&self, arg: T) -> R;
        }

        struct Ttt;

        impl CallCore11<String, String> for Ttt {
            async fn run(&self, arg: String) -> String {
                arg
            }
        }

        let ttt = Ttt;
        let s = ttt.run("test".to_string()).await;
        println!("{}", s);
        assert_eq!(s, "test");


        struct MultiContainer {
            data: HashMap<TypeId, Box<dyn Any>>,
        }
        
        impl MultiContainer {
            pub fn new() -> Self {
                Self { data: HashMap::new() }
            }
        
            // 存储或更新某个类型的值
            pub fn store<T: Any + 'static>(&mut self, value: T) {
                self.data.insert(TypeId::of::<T>(), Box::new(value));
            }
        
            // 获取某个类型的不可变引用
            pub fn get<T: Any + 'static>(&self) -> Option<&T> {
                self.data.get(&TypeId::of::<T>()).and_then(|b| b.downcast_ref())
            }
        
            // 获取某个类型的可变引用
            pub fn get_mut<T: Any + 'static>(&mut self) -> Option<&mut T> {
                self.data.get_mut(&TypeId::of::<T>()).and_then(|b| b.downcast_mut())
            }
        }
    }
}
